<template>
  <!-- 自定义排班 -->
  <div class="custom-shift" @click="currentCell = {}">
    <a-page-header class="header" title="排班管理" @back="goBack">
    </a-page-header>
    <section class="content">
      <a-form :label-col="labelCol" :wrapper-col="wrapperCol" labelAlign="left">
        <a-form-item label="排班班次">
          <a-row type="flex" align="middle" :gutter="[8, 8]" :wrap="true">
            <a-col
              v-for="item of selectedShifts"
              :key="item.id"
              style="display: flex; align-items: center"
            >
              <a-tag
                :color="item.color"
                style="max-width: 160px"
                class="nowrap"
              >
                {{ item.shift_name }}
              </a-tag>
            </a-col>
            <a-col>
              <a-button type="link" @click="chooseShiftsVisible = true">
                添加
              </a-button>
            </a-col>
          </a-row>
        </a-form-item>
        <a-form-item label="排班周期">
          <a-table
            v-if="cycleList.length"
            size="small"
            :bordered="true"
            :columns="cycleColumns"
            :dataSource="cycleList"
            :pagination="false"
            rowKey="cycle_name"
          >
            <template #bodyCell="{ text, record, index, column }">
              <template v-if="column.key === 'cycle_list'">
                {{ getCycleList(text) }}
              </template>
              <template v-if="column.key === 'action'">
                <a-button type="link" @click="setCycle(record)">
                  设置
                </a-button>
              </template>
            </template>
          </a-table>
          <a-button v-else type="link" @click="setCycle()"> 点击设置 </a-button>
        </a-form-item>
        <a-row type="flex" align="middle" justify="space-between">
          <a-col>
            <a-space>
              <a-month-picker
                :value="shiftMonth"
                placeholder="请选择月份"
                :format="monthFormat"
                :valueFormat="monthFormat"
                :allowClear="false"
                @change="handleShiftMonthChange"
              />
              <a-input-search
                v-model:value="name"
                placeholder="可输入员工姓名搜索"
                :allowClear="true"
              />
            </a-space>
          </a-col>
          <a-col v-if="changedKey.length">
            <a-space>
              <span>已调整 {{ changedKey.length }} 项</span>
              <a-button type="primary" @click="saveMemberShift">保存</a-button>
              <a-button @click="resetMemberShift"> 恢复 </a-button>
            </a-space>
          </a-col>
        </a-row>
        <section class="mt-20">
          <a-table
            size="small"
            :bordered="true"
            :columns="dateColumns"
            :scroll="{ x: 'max-content' }"
            :dataSource="renderMemberList"
            :pagination="false"
            :loading="memberLoading"
            rowKey="uid"
          >
            <template v-for="col of dateArr" :key="col.dateKey" #[col.dateKey]>
              <div>{{ col.date }}</div>
              <div>{{ col.week }}</div>
            </template>
            <template
              v-for="col of dateArr"
              :key="col.contentKey"
              #[col.contentKey]="{ record, column, text }"
            >
              <a-popover trigger="hover" v-if="text != null">
                <template #content>
                  <div>
                    {{
                      shiftListMap[text]
                        ? shiftListMap[text].shift_name
                        : allShiftMap[text]
                    }}
                  </div>
                </template>
                <a-popover
                  :visible="
                    currentCell.uid == record.uid &&
                    currentCell.key == column.key
                  "
                  trigger="click"
                  placement="bottom"
                >
                  <template #title>
                    <a-radio-group
                      v-model:value="shiftType"
                      button-style="solid"
                    >
                      <a-radio-button value="shift">按班次排班</a-radio-button>
                      <a-radio-button
                        :disabled="!cycleList.length"
                        value="cycle"
                      >
                        按周期排班
                      </a-radio-button>
                    </a-radio-group>
                  </template>
                  <template #content>
                    <div
                      v-if="shiftType == 'shift'"
                      class="content-box"
                      @click.stop
                    >
                      <div class="shift-tip">修改该成员当天班次</div>
                      <div
                        v-for="item of selectedShifts"
                        :key="item.id"
                        :style="{ background: item.color }"
                        class="shift-box"
                        @click="setMemberShift(record, column, item.id)"
                      >
                        {{ item.shift_name }}
                      </div>
                      <div
                        class="shift-box clear"
                        key="clear"
                        @click="setMemberShift(record, column, null)"
                      >
                        清空
                      </div>
                    </div>
                    <div
                      v-if="shiftType == 'cycle'"
                      class="content-box"
                      @click.stop
                    >
                      <div class="shift-tip">
                        从该天开始，按周期排班，直至本月最后一天
                      </div>
                      <div
                        v-for="(item, index) of cycleList"
                        :key="index"
                        style="background: #2681f3"
                        class="shift-box"
                        @click="setMemberShift(record, column, item)"
                      >
                        {{ item.cycle_name }}
                      </div>
                    </div>
                  </template>
                  <div
                    class="cell"
                    :class="{
                      'cell-active':
                        currentCell &&
                        currentCell.uid == record.uid &&
                        currentCell.key == column.key,
                    }"
                    :style="
                      text != null && shiftListMap[text]
                        ? 'color: #fff;background:' + shiftListMap[text].color
                        : ''
                    "
                    @click.stop="handleCellClick(column, record)"
                  >
                    <div v-if="text != null" class="cell-text">
                      {{
                        shiftListMap[text]
                          ? shiftListMap[text].shift_name
                          : allShiftMap[text]
                      }}
                    </div>
                    <a-badge
                      v-if="
                        changedKey.length &&
                        changedKey.includes(record.uid + '_' + column.key)
                      "
                      class="badge"
                      status="error"
                    />
                  </div>
                </a-popover>
              </a-popover>
              <a-popover
                v-else
                :visible="
                  currentCell.uid == record.uid && currentCell.key == column.key
                "
                trigger="click"
                placement="bottom"
              >
                <template #title>
                  <a-radio-group v-model:value="shiftType" button-style="solid">
                    <a-radio-button value="shift">按班次排班</a-radio-button>
                    <a-radio-button :disabled="!cycleList.length" value="cycle">
                      按周期排班
                    </a-radio-button>
                  </a-radio-group>
                </template>
                <template #content>
                  <div
                    v-if="shiftType == 'shift'"
                    class="content-box"
                    @click.stop
                  >
                    <div class="shift-tip">修改该成员当天班次</div>
                    <div
                      v-for="item of selectedShifts"
                      :key="item.id"
                      :style="{ background: item.color }"
                      class="shift-box"
                      @click="setMemberShift(record, column, item.id)"
                    >
                      {{ item.shift_name }}
                    </div>
                    <div
                      class="shift-box clear"
                      key="clear"
                      @click="setMemberShift(record, column, null)"
                    >
                      清空
                    </div>
                  </div>
                  <div
                    v-if="shiftType == 'cycle'"
                    class="content-box"
                    @click.stop
                  >
                    <div class="shift-tip">
                      从该天开始，按周期排班，直至本月最后一天
                    </div>
                    <div
                      v-for="(item, index) of cycleList"
                      :key="index"
                      style="background: #2681f3"
                      class="shift-box"
                      @click="setMemberShift(record, column, item)"
                    >
                      {{ item.cycle_name }}
                    </div>
                  </div>
                </template>
                <div
                  class="cell"
                  :class="{
                    'cell-active':
                      currentCell &&
                      currentCell.uid == record.uid &&
                      currentCell.key == column.key,
                  }"
                  :style="
                    text != null && shiftListMap[text]
                      ? 'color: #fff;background:' + shiftListMap[text].color
                      : ''
                  "
                  @click.stop="handleCellClick(column, record)"
                >
                  <a-badge
                    v-if="
                      changedKey.length &&
                      changedKey.includes(record.uid + '_' + column.key)
                    "
                    class="badge"
                    status="error"
                  />
                </div>
              </a-popover>
            </template>
          </a-table>
        </section>
      </a-form>
    </section>
    <ChooseShifts
      checkType="checkbox"
      :min="0"
      :visible="chooseShiftsVisible"
      :selectedKeys="selectedShiftKeys"
      @cancel="chooseShiftsVisible = false"
      @success="handleShiftChooseSuccess"
    />
    <SetShiftCycle
      :visible="setCycleVisible"
      :detail="cycleDetail"
      :shiftList="selectedShifts"
      @cancel="setCycleVisible = false"
      @success="setCycleSuccess"
    />
  </div>
</template>

<script>
import { message } from "ant-design-vue";
import moment from "moment";
import { computed, defineComponent, reactive, toRaw, toRefs, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import request from "../../../common/utils/request";
import utils from "../../../common/utils/utils";
import ChooseShifts from "./modules/ChooseShifts.vue";
import SetShiftCycle from "./modules/SetShiftCycle.vue";

const colorList = ["#6691f7", "#ea6d74", "#f19851", "#7a6ecd", "#5cb48a"];
let colorIndex = -1;
const monthFormat = "YYYY-MM";
const dayFormat = "YYYY-MM-DD";
const nameCol = {
  dataIndex: "realname",
  title: "姓名",
  width: 100,
  fixed: "left",
  align: "center",
};
const weekObj = {
  0: "日",
  1: "一",
  2: "二",
  3: "三",
  4: "四",
  5: "五",
  6: "六",
};
const relaxShift = {
  id: 0,
  shift_name: "休息",
  color: "#cccccc",
};

export default defineComponent({
  name: "CustomShift",
  components: { ChooseShifts, SetShiftCycle },
  setup() {
    const $router = useRouter();
    const $route = useRoute();
    const state = reactive({
      monthFormat,
      id: $route.query.id,
      detail: {},
      chooseShiftsVisible: false,
      selectedShiftKeys: [],
      selectedShifts: [relaxShift],
      shiftListMap: {
        0: relaxShift,
      },
      allShiftMap: {},
      shiftMonth: moment().format(monthFormat),
      daysCount: 0,
      nowDay: moment().format(dayFormat),
      name: "",
      dateColumns: [],
      dateArr: [],
      originMemberList: [],
      memberList: [],
      setCycleVisible: false,
      cycleDetail: {},
      cycleList: [],
      shiftList: [],
      currentCell: {},
      shiftType: "shift",
      changedKey: [],
      memberLoading: false,
    });

    const renderMemberList = computed(() => {
      let result = state.memberList;
      if (state.name) {
        result = state.memberList.filter(
          (item) => item.realname.indexOf(state.name) != -1
        );
      }
      return result;
    });

    // 设置周期
    const setCycle = (detail) => {
      if (detail) {
        state.cycleDetail = detail;
      }
      state.setCycleVisible = true;
    };
    const setCycleSuccess = (e) => {
      state.cycleList = [e.detail];
      state.setCycleVisible = false;
      setSettingData();
    };
    const getCycleList = (list) => {
      const arr = list.map(
        (item) => state.shiftListMap[item.shift_id].shift_name
      );
      return arr.join("-");
    };

    // 选择班次
    const handleShiftChooseSuccess = (detail) => {
      // 对比keys是否有被删除
      let delShifts = [];
      for (let item of state.selectedShifts) {
        if (item.id && !detail.keys.includes(item.id)) {
          delShifts.push(item);
        }
      }
      if (delShifts.length) {
        const names = delShifts.map((item) => item.shift_name);
        utils.modalConfirm({
          content: `确定从排班组删除“${names.join(
            ","
          )}”等班次吗？删除后，当前排班周期将自动删除，但是排班表中已排班次不受影响。`,
          okType: "danger",
          onOk: () => {
            state.cycleList = [];
            setShiftDetail(detail);
            getMemberList();
          },
        });
      } else {
        setShiftDetail(detail);
      }
    };
    const setShiftDetail = (detail) => {
      state.shiftListMap = {
        0: relaxShift,
      };
      colorIndex = -1;
      state.selectedShifts = detail.list.map((item) => {
        colorIndex++;
        if (!colorList[colorIndex]) {
          colorIndex = 0;
        }
        item.color = colorList[colorIndex];
        state.shiftListMap[item.id] = item;
        return item;
      });
      state.selectedShifts.push(relaxShift);
      state.selectedShiftKeys = detail.keys;
      state.chooseShiftsVisible = false;
      setSettingData();
    };
    const setSettingData = () => {
      request.put("/org", "/shift/group/set", {
        id: state.id,
        time_detail: {
          shift_ids: state.selectedShiftKeys,
          shift_cycle: state.cycleList,
        },
      });
    };

    // 切换日期
    const handleShiftMonthChange = (val) => {
      console.log("handleShiftMonthChange", val);
      if (state.changedKey.length) {
        utils.modalConfirm({
          title: "当月排班信息尚未保存",
          content: `你确定放弃对排班信息的修改吗？`,
          okType: "danger",
          onOk: () => {
            state.shiftMonth = val;
            state.daysCount = moment(state.shiftMonth).daysInMonth();
            getMemberTable();
            getMemberList();
          },
        });
      } else {
        state.shiftMonth = val;
        state.daysCount = moment(state.shiftMonth).daysInMonth();
        getMemberTable();
        getMemberList();
      }
    };

    // 整理表头
    const getMemberTable = () => {
      state.dateColumns = [nameCol];
      state.dateArr = [];
      for (let i = 1; i <= state.daysCount; i++) {
        let dateKey = `shift_${i}`;
        let contentKey = `content_${i}`;
        state.dateColumns.push({
          key: i,
          dataIndex: dateKey,
          width: 40,
          align: "center",
          customHeaderCell,
          customCell,
          slots: { title: dateKey, customRender: contentKey },
        });
        let day = `${state.shiftMonth}-${i < 10 ? "0" + i : i}`;
        state.dateArr.push({
          dateKey,
          contentKey,
          date: i,
          day,
          week: weekObj[moment(day).day()],
        });
      }
    };
    const customHeaderCell = (column) => {
      let style = {
        overflow: "hidden",
      };
      if (
        state.nowDay ==
        `${state.shiftMonth}-${column.key < 10 ? "0" + column.key : column.key}`
      ) {
        style.background = "#2681f3";
        style.color = "#fff";
      }
      return {
        style,
      };
    };
    const customCell = (record, rowIndex, e) => {
      // console.log("customCell", rowIndex, record, e);
      let cellStyle = {
        padding: 0,
        cursor: "pointer",
      };
      return {
        style: cellStyle,
      };
    };

    const handleCellClick = (column, record) => {
      state.shiftType = "shift";
      state.currentCell = {
        uid: record.uid,
        key: column.key,
      };
    };

    // 设置排班
    const setMemberShift = (current, column, value) => {
      state.currentCell = {};
      if (current[column.dataIndex] == value) {
        return;
      }
      if (state.shiftType == "shift") {
        current[column.dataIndex] = value;
        const changedKey = `${current.uid}_${column.key}`;
        const index = state.changedKey.findIndex((item) => item == changedKey);
        if (index == -1) {
          state.changedKey.push(changedKey);
        }
      }
      if (state.shiftType == "cycle") {
        const { cycle_list } = value;
        let cycleIndex = -1;
        for (let i = column.key; i <= state.daysCount; i++) {
          cycleIndex++;
          if (!cycle_list[cycleIndex]) {
            cycleIndex = 0;
          }
          current[`shift_${i}`] = cycle_list[cycleIndex].shift_id;
          const changedKey = `${current.uid}_${i}`;
          const index = state.changedKey.findIndex(
            (item) => item == changedKey
          );
          if (index == -1) {
            state.changedKey.push(changedKey);
          }
        }
      }
    };

    // 恢复默认
    const resetMemberShift = () => {
      state.memberList = JSON.parse(JSON.stringify(state.originMemberList));
      state.changedKey = [];
    };

    // 保存排班
    const saveMemberShift = () => {
      console.log("saveMemberShift", toRaw(state.memberList));
      const params = {
        group_id: state.id,
        year_month: state.shiftMonth,
        shift_detail: [],
        needMsg: true,
      };
      for (let member of state.memberList) {
        let newItem = {
          uid: member.uid,
          shift: [],
        };
        for (let key in member) {
          if (member[key] != null && key.indexOf("shift") != -1) {
            const day = key.split("_")[1];
            newItem.shift.push({
              day: Number(day),
              shift_id: member[key],
            });
          }
        }
        params.shift_detail.push(newItem);
      }
      console.log("====================saveMemberShift", toRaw(params));
      request.post("/org", "/shift/detail", params).then((res) => {
        message.success(res.msg || "保存成功！");
        getMemberList();
      });
    };

    // 排班人员班次情况
    const getMemberList = () => {
      state.memberLoading = true;
      state.changedKey = [];
      request
        .get("/org", "/shift/detail", {
          group_id: state.id,
          year_month: state.shiftMonth,
        })
        .then((res) => {
          if (res.list && res.list.length) {
            state.memberList = res.list.map((user) => {
              let newItem = {
                uid: user.uid,
                realname: user.realname,
              };
              let shift_detail = {};
              if (user.shift_detail && user.shift_detail.length) {
                for (let item of user.shift_detail) {
                  shift_detail[item.day] = item.shift_id;
                }
              }
              for (let i = 1; i <= state.daysCount; i++) {
                newItem[`shift_${i}`] =
                  shift_detail[i] || shift_detail[i] == 0
                    ? shift_detail[i]
                    : null;
              }
              return newItem;
            });
            state.originMemberList = JSON.parse(
              JSON.stringify(state.memberList)
            );
          }
          state.memberLoading = false;
        });
    };

    const getDetail = () => {
      request
        .get("/org", "/shift/group", {
          id: state.id,
        })
        .then((res) => {
          const { detail } = res;
          state.detail = detail;
          if (
            detail.time_detail.shift_ids &&
            detail.time_detail.shift_ids.length
          ) {
            colorIndex = -1;
            state.selectedShiftKeys = detail.time_detail.shift_ids;
            state.selectedShifts = detail.time_detail.shift.map((item) => {
              item.time_detail = utils.getShiftTimeDetail(item.time_detail);
              colorIndex++;
              if (!colorList[colorIndex]) {
                colorIndex = 0;
              }
              item.color = colorList[colorIndex];
              state.shiftListMap[item.id] = item;
              return item;
            });
            state.selectedShifts.push(relaxShift);
          }
          if (
            detail.time_detail.shift_cycle &&
            detail.time_detail.shift_cycle.length
          ) {
            state.cycleList = detail.time_detail.shift_cycle;
          }
        });
    };
    const goBack = () => {
      $router.go(-1);
    };

    const getShiftList = () => {
      request.get("/org", "/shift/list").then((res) => {
        res.list.forEach((item) => {
          state.allShiftMap[item.id] = item.shift_name;
        });
      });
    };

    const init = () => {
      state.daysCount = moment(state.shiftMonth).daysInMonth();
      getDetail();
      getMemberTable();
      getMemberList();
      getShiftList();
    };
    init();

    return {
      labelCol: {
        style: { width: "100px" },
      },
      wrapperCol: {
        span: 16,
      },
      cycleColumns,
      renderMemberList,
      ...toRefs(state),
      goBack,
      handleShiftChooseSuccess,
      setCycle,
      setCycleSuccess,
      getCycleList,
      handleCellClick,
      setMemberShift,
      resetMemberShift,
      saveMemberShift,
      handleShiftMonthChange,
    };
  },
});
const cycleColumns = [
  {
    title: "周期名称",
    dataIndex: "cycle_name",
    align: "center",
  },
  {
    title: "周期班次",
    dataIndex: "cycle_list",
    key: "cycle_list",
    align: "center",
  },
  {
    title: "周期天数",
    dataIndex: "cycle_days",
    align: "center",
  },
  {
    title: "操作",
    dataIndex: "cycle_name",
    key: "action",
    align: "center",
  },
];
</script>

<style lang="less" scoped>
.custom-shift {
  width: 100%;
  height: 100%;
  background: #fff;
  border-left: 1px solid #f1f1f1;
  display: flex;
  flex-direction: column;
  .content {
    flex: 1;
    overflow: hidden auto;
    padding: 20px;
    .cell {
      height: 40px;
      width: 100%;
      padding: 0 5px;
      display: flex;
      align-items: center;
      justify-content: center;
      position: relative;
      overflow: hidden;
      text-overflow: ellipsis;
      font-size: 12px;
      line-height: 20px;
      .cell-text {
        max-height: 100%;
        overflow: hidden;
      }
      .badge {
        position: absolute;
        right: -6px;
        top: -6px;
      }
    }
    .cell-active {
      border: 1px solid @primary-color;
    }
  }
}
.content-box {
  width: 200px;
  .shift-tip {
    text-align: center;
    color: #999;
    padding-bottom: 10px;
    color: 12px;
  }
  .shift-box {
    border-radius: 4px;
    text-align: center;
    color: #fff;
    padding: 5px 10px;
    margin-bottom: 10px;
    cursor: pointer;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .clear {
    color: @error-color;
    border: 1px solid @error-color;
  }
}
</style>
